package pub.tbc.api.service;

import com.google.common.collect.Maps;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 服务映射配置表
 *
 * @author tbc on 2017/3/18.
 */
@Slf4j
@Data
public class ServiceConfigTable {
    private static String CLASS_PATH = ServiceConfigTable.class.getResource("/").getPath();
    private static String CONFIG_FILE_NAME = "serviceConfigTable.xml";
    private static String CONFIG_FILE = CLASS_PATH + "/" + CONFIG_FILE_NAME;

    /**
     * 服务信息列表
     */
    private List<ServiceInfo> serviceInfoList = new ArrayList<>();

    /**
     * 存放服务名：服务对象的映射
     */
    @Getter
    private Map<String, ServiceInfo> serviceMap = Maps.newHashMap();

    private static ServiceConfigTable instance;

    public static ServiceConfigTable getInstance() {
        if (instance == null) {
            try {
                File loadFile = new File(CONFIG_FILE);
                if (!loadFile.exists()) {
                    log.info("映射文件不存在！");
                    instance = new ServiceConfigTable();
                    instance.save();
                    instance.serviceMapInit();
                } else {
                    log.info("实例化服务配置表...");
                    XMLDecoder decoder = new XMLDecoder(new FileInputStream(loadFile));
                    instance = (ServiceConfigTable) decoder.readObject();
                    instance.serviceMapInit();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return instance;
    }

    private void save() throws IOException {
        File file = new File(CONFIG_FILE);
        if (!file.exists()) {
            file.createNewFile();
        }
        XMLEncoder encoder = new XMLEncoder(new FileOutputStream(file));
        encoder.writeObject(this);
        encoder.close();
    }

    /**
     * 初始化映射对象
     */
    private void serviceMapInit() {
        // 无校验PUT，如果配置文件中配置了多个重复服务，将以最后一个为准
        serviceInfoList.forEach(serviceInfo -> serviceMap.put(serviceInfo.getServiceName(), serviceInfo));
    }

    private String traceServiceName(String serviceName) {
        if (serviceMap.keySet().contains(serviceName)) return serviceName;
        return null;
    }

    /**
     * 服务配置信息中是否存在指定服务
     *
     * @param serviceName 服务名
     * @return boolean
     */
    public boolean contain(String serviceName) {
        Optional<ServiceInfo> optional = serviceInfoList.stream()
                .filter(serviceInfo -> serviceInfo.getServiceName().equalsIgnoreCase(serviceName))
                .findFirst();
//        return optional.map(serviceInfo -> true).orElse(false);
        return optional.isPresent();
    }


    /**
     * 使用该方法前需要确定配置表中存在该服务
     *
     * @param serviceName 服务名
     * @return ServiceInfo
     */
    public ServiceInfo getServiceInfo(String serviceName) {
        return serviceMap.get(serviceName);
    }

}
